www.gusucode.com > VC 串口封装类(支持同步与异步)-源码程序 > VC 串口封装类(支持同步与异步)-源码程序/code/Zcomm.cpp
//Download by http://www.NewXing.com #include <stdio.h> #include "stdafx.h" #include "zcomm.h" //DWORD FAR PASCAL CommWatchProc( LPSTR lpData ); ZComm::ZComm() { fConnected=0; fCOMMOpened=0; olap=FALSE; } ZComm::~ZComm() { if (fCOMMOpened==1) { fCOMMOpened=0; PurgeComm( idComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ; if (olap){ CloseHandle( READ_OS.hEvent ) ; CloseHandle( WRITE_OS.hEvent ) ; } CloseHandle(idComDev) ; olap=FALSE; } } ZComm::open(char *szPort,int Baud_rate, BOOL overlapped) { int retbuflength=0; if (overlapped) { //异步方式打开串口 memset( &READ_OS, 0, sizeof( OVERLAPPED ) ) ; memset( &WRITE_OS, 0, sizeof( OVERLAPPED ) ) ; READ_OS.hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset req FALSE, // initial event reset NULL ) ; // no name if (READ_OS.hEvent == NULL) return -1 ; WRITE_OS.hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset req FALSE, // initial event reset NULL ) ; // no name if (NULL == WRITE_OS.hEvent) { CloseHandle( READ_OS.hEvent ) ; return -1 ; } idComDev=CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, // exclusive access NULL, // no security attrs OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL| FILE_FLAG_OVERLAPPED, // overlapped I/O NULL ); olap=TRUE; } //同步方式打开串口 else idComDev=CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, // exclusive access NULL, // no security attrs OPEN_EXISTING, 0, //is overlapped or no NULL ); if (idComDev==(HANDLE) -1){ DWORD RR=GetLastError(); CloseHandle(idComDev) ; if (olap){ CloseHandle( READ_OS.hEvent ) ; CloseHandle( WRITE_OS.hEvent ) ; } fCOMMOpened=0; olap=FALSE; return (0); } set_baudrate(Baud_rate); fCOMMOpened=1; SetupComm(idComDev,11520,2048); PurgeComm(idComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ; SetCommMask(idComDev, EV_RXFLAG ); //set time out SetTimeOut(10,100,500); return (1); } BOOL ZComm::SetTimeOut(DWORD ReadIntervalTimeout, DWORD ReadTotalTimeoutMultiplier, DWORD ReadTotalTimeoutConstant) { COMMTIMEOUTS timeouts; GetCommTimeouts(idComDev,&timeouts); timeouts.ReadIntervalTimeout=ReadIntervalTimeout; timeouts.ReadTotalTimeoutMultiplier=ReadTotalTimeoutMultiplier; timeouts.ReadTotalTimeoutConstant=ReadTotalTimeoutConstant; return SetCommTimeouts(idComDev,&timeouts); } ZComm::Close() { if (fCOMMOpened==1) { fCOMMOpened=0; CloseHandle(idComDev) ; olap=FALSE; if (olap){ CloseHandle( READ_OS.hEvent ) ; CloseHandle( WRITE_OS.hEvent ) ; } return 1; } return 0; } int ZComm::set_baudrate(int baud_rate) { DCB dcb; BOOL fsuccess; fsuccess = GetCommState(idComDev, &dcb); if (!fsuccess) return 0; dcb.BaudRate =baud_rate; dcb.ByteSize =8; //number of bits/byte, 4-8 dcb.Parity =NOPARITY; dcb.StopBits =ONESTOPBIT; dcb.EvtChar=0x02; //dcb.fNull=TRUE; fsuccess=SetCommState(idComDev, &dcb); if (!fsuccess) return 0; return 1; } // USE BY READSTREAM() // DWORD ZComm::ReadByte(BYTE * buf) { OVERLAPPED os; BOOL fReadStat; DWORD dwEvtMask; DWORD dwErrorFlags; COMSTAT ComStat; DWORD dwLength; if (fCOMMOpened==0) return 0; //串口未打开 if (olap) // OVERLAPPED { SetCommMask(idComDev, EV_RXCHAR ); memset( &os, 0, sizeof( OVERLAPPED )); os.hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset req FALSE, // initial event nonsignaled. NULL ) ; // no name if (os.hEvent == NULL) { OutputDebugString("\n\r Failed to create event for ReadByte"); CloseHandle(os.hEvent); return 0; } dwEvtMask = 0 ; WaitCommEvent(idComDev,&dwEvtMask,&os); if (WaitForSingleObject(os.hEvent,MAXTIMEOUT)==WAIT_TIMEOUT) { OutputDebugString("\n\r time out for ReadByte"); CloseHandle(os.hEvent); return 0; } if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR) { ClearCommError(idComDev, &dwErrorFlags, &ComStat); dwLength = max(1,ComStat.cbInQue); //dwLength=1; fReadStat = ReadFile( idComDev,buf,dwLength,&dwLength, &READ_OS); if (!fReadStat) { OutputDebugString("\n\r can not Read Byte"); CloseHandle(os.hEvent); return 0; } else{ CloseHandle(os.hEvent); return dwLength; } } else{ CloseHandle(os.hEvent); return 0; } } else{ //NOT OVERLAPPED dwLength=0; ReadFile(idComDev,buf,1,&dwLength, &READ_OS); return dwLength; } } // USE READBYTE() // DWORD ZComm::ReadStream(BYTE *buf,int Length) { BYTE temp[1024]; DWORD ret; int i=0; if (Length<=0) return 0; while(i<Length){ ret=0; memset(temp,0,1024); ret=ReadByte(temp); //PurgeComm( idComDev,PURGE_RXCLEAR); if (ret==0) return 0; if ((int)(ret+i)>Length) { memcpy(buf+i,temp,Length); } else memcpy(buf+i,temp,ret); i+=ret; } return i; } // used BY sendcommand() // ZComm::Read(BYTE *buf,int nMaxLength) { BOOL fReadStat ; COMSTAT ComStat; DWORD dwErrorFlags; DWORD dwLength; DWORD dwError; char szError[ 10 ]; if (fCOMMOpened==0) return 0; //串口未打开 // only try to read number of bytes in queue ClearCommError(idComDev, &dwErrorFlags, &ComStat) ; //dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ; dwLength=nMaxLength; if (dwLength > 0) { if (olap==TRUE) { fReadStat = ReadFile(idComDev,buf, dwLength, &dwLength,&READ_OS) ; if (!fReadStat) { if (GetLastError() == ERROR_IO_PENDING) { OutputDebugString("\n\rIO Pending"); while(!GetOverlappedResult(idComDev, &READ_OS, &dwLength, TRUE )) { dwError = GetLastError(); if(dwError == ERROR_IO_INCOMPLETE) continue; else { // an error occurred, try to recover ClearCommError(idComDev,&dwErrorFlags, &ComStat ) ; break; } } } else // end-----if (GetLastError() == ERROR_IO_PENDING) { // some other error occurred dwLength = 0 ; ClearCommError(idComDev, &dwErrorFlags, &ComStat ) ; if (dwErrorFlags >0) { wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ; OutputDebugString(szError); } } } // end-----if (!fReadStat) } // end-----if (olap==TRUE) else { fReadStat = ReadFile( idComDev,buf, dwLength, &dwLength, NULL ) ; if (!fReadStat) { dwError = GetLastError(); ClearCommError(idComDev,&dwErrorFlags, &ComStat ) ; if (dwErrorFlags >0) { wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ; OutputDebugString(szError); } } } } return dwLength; } int ZComm::ReadString(void* pData, int nLength) { DWORD dwNumRead; // 串口收到的数据长度 ReadFile(idComDev, pData, (DWORD)nLength, &dwNumRead, NULL); return (int)dwNumRead; } ZComm::Write(BYTE *buf,int buflen) { BOOL fWriteStat; DWORD dwErrorFlags; DWORD dwError; COMSTAT ComStat; char szError[ 10 ] ; DWORD ret; if (fCOMMOpened==0) return -2 ;//串口未打开 ret=0; if (olap) { fWriteStat = WriteFile(idComDev,buf,buflen,&ret, &WRITE_OS ) ; if (!fWriteStat) { if ((dwError=GetLastError()) == ERROR_IO_PENDING) { while (!GetOverlappedResult(idComDev,&WRITE_OS,&ret, TRUE )) { dwError = GetLastError(); if(dwError == ERROR_IO_INCOMPLETE) { OutputDebugString("write io pending"); continue; } else { //an error occurred, try to recover wsprintf( szError, "\n\r <CE-%u>", dwError ) ; OutputDebugString(szError); ClearCommError(idComDev, &dwErrorFlags, &ComStat ) ; if (dwErrorFlags > 0) { wsprintf( szError, "\n\r <CE-%u>",dwErrorFlags ) ; OutputDebugString(szError); } break; } } } else { // some other error occurred wsprintf( szError, "\n\r <CE-%u>", dwError ) ; OutputDebugString(szError); ClearCommError(idComDev,&dwErrorFlags,&ComStat ) ; if (dwErrorFlags>0) { wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags) ; OutputDebugString(szError); } return ( FALSE ); } } } else { fWriteStat = WriteFile(idComDev, buf,(DWORD)buflen,&ret, NULL); if (!fWriteStat) { if(GetLastError() == ERROR_IO_PENDING) { dwError = GetLastError(); // an error occurred, try to recover wsprintf( szError, "\n\r <CE-%u>", dwError ) ; OutputDebugString(szError); ClearCommError(idComDev, &dwErrorFlags, &ComStat ) ; if (dwErrorFlags >0) { wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ; OutputDebugString(szError); } } else { // some other error occurred ClearCommError(idComDev, &dwErrorFlags, &ComStat ) ; if (dwErrorFlags > 0) { wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ; OutputDebugString(szError); } return ( FALSE ); } } } return (ret); } bool ZComm::SendStrCommand(CString CommandWord) //发送字符串命令 { DWORD t1,dwRead; COMSTAT t2; CString Command(""); Command+=CommandWord; // 组合命令串 WriteFile( idComDev, Command.GetBuffer (Command.GetLength ()), Command.GetLength (), &dwRead, NULL); if(!ClearCommError(idComDev,&t1,&t2)) { switch(t1) { case CE_OOP: TRACE("G CE_OOP\n"); return false; break; case CE_PTO://超时错误 TRACE("G CE_PTO\n"); return false; break; case CE_IOE: TRACE("G CE_IOE\n"); return false; break; } } return true; } CString ZComm::ReceiveATInfo() { char tmp[2]; DWORD dwBytesRead; CString retvalue; int i(0), iCount(0); BOOL bReturn; memset(tmp,0,2); bReturn = ReadFile(idComDev, tmp, 1, &dwBytesRead, NULL); if (dwBytesRead < 1) { return ""; } do { retvalue += tmp; memset(tmp,0,2); bReturn = ReadFile(idComDev, tmp, 1, &dwBytesRead, NULL); i++; } while(dwBytesRead == 1); return retvalue; } int ZComm::sendcommand(BYTE *buf,int buflen,char * reply,int *len_reply) { OVERLAPPED os; char abIn[1024]; int nLength; DWORD dwEvtMask; if (olap) { nLength=0; *len_reply=0; strcpy(reply,""); memset( &os, 0, sizeof( OVERLAPPED )); os.hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset req FALSE, // initial event nonsignaled. NULL ) ; // no name if (os.hEvent == NULL) { OutputDebugString("\n\r Failed to create event for thread"); return 0; } PurgeComm( idComDev, PURGE_TXABORT | PURGE_RXABORT |PURGE_TXCLEAR | PURGE_RXCLEAR ) ; Write(buf,buflen); dwEvtMask = 0 ; WaitCommEvent(idComDev,&dwEvtMask,&os ); if (WaitForSingleObject(os.hEvent,MAXTIMEOUT)==WAIT_TIMEOUT){ PurgeComm( idComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); return 0; } do{ memset(abIn,0,1024); if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR) { //Sleep(5); nLength =Read((BYTE *) abIn,1024); strcat(reply,abIn); *len_reply+=nLength; } //ResetEvent(os.hEvent); OutputDebugString(abIn); OutputDebugString("\n"); }while (abIn[nLength-1]!=0x03); CloseHandle( os.hEvent ) ; return 1 ; }else return -2; } int ZComm::CheckICC (int cmd,BYTE *buf) { int i; BYTE c=0; if (cmd==1) { for(i=0;i<3;i++) c=c^buf[i]; if (buf[3]==c) return COMSUCCESS; } if (cmd==4) { for(i=0;i<19;i++) c=c^buf[i]; if (buf[19]==c) return COMSUCCESS; } if (cmd==0xe0) { for(i=0;i<3;i++) c=c^buf[i]; if (buf[3]==c) return COMSUCCESS ; } return FAILURE; } BYTE ZComm::CalculateICC (int cmd,BYTE *buf) { int i; BYTE c=0; if (cmd==1) { for(i=0;i<11;i++) c=c^buf[i]; buf[11]=c; } if (cmd==2) { for(i=0;i<buf[1]+2;i++) c=c^buf[i]; buf[buf[1]+2]=c; } if (cmd==3) { for(i=0;i<3;i++) c=c^buf[i]; buf[4]=c; } if (cmd==4) { for(i=0;i<5;i++) c=c^buf[i]; buf[5]=c; } if (cmd==0xe0) { for(i=0;i<3;i++) c=c^buf[i]; buf[4]=c; } return c; } BOOL ZComm::Purge() { PurgeComm( idComDev,PURGE_TXABORT | PURGE_RXABORT); return PurgeComm( idComDev,PURGE_TXCLEAR | PURGE_RXCLEAR); } BOOL ZComm::PurgeIn() { return PurgeComm( idComDev, PURGE_RXCLEAR); } BOOL ZComm::WaitEventChar() { OVERLAPPED os ; DWORD dwEvtMask,Errors; COMSTAT Stat; memset( &os, 0, sizeof( OVERLAPPED )); os.hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset req FALSE, // initial event nonsignaled. NULL ) ; // no name dwEvtMask = 0 ; WaitCommEvent(idComDev,&dwEvtMask,&os); if (WaitForSingleObject(os.hEvent,MAXTIMEOUT)==WAIT_TIMEOUT) { CloseHandle(os.hEvent); return false; } else if ((dwEvtMask & EV_RXFLAG) == EV_RXFLAG) { CloseHandle(os.hEvent); ClearCommError(idComDev,&Errors, &Stat); return true; }else { CloseHandle(os.hEvent); return false; } } BOOL ZComm::SetEventChar(char EventChar) { DCB dcb; BOOL fsuccess; fsuccess = GetCommState(idComDev, &dcb); if (!fsuccess) return false; dcb.EvtChar= EventChar; fsuccess=SetCommState(idComDev, &dcb ) ; return fsuccess; } BOOL ZComm::FlashCommMask() { DWORD dwEvtMask; GetCommMask(idComDev, &dwEvtMask); return SetCommMask(idComDev,dwEvtMask); } BOOL ZComm::SetRTS(int set) { if (set==1){ return EscapeCommFunction(idComDev,SETRTS); } else{ return EscapeCommFunction(idComDev,CLRRTS); } return 0; } void ZComm::crc_16(BYTE *data, int length, BYTE *reply) { static WORD CRCTABLE[256]={ 0xF078,0xE1F1,0xD36A,0xC2E3,0xB65C,0xA7D5,0x954E,0x84C7, 0x7C30,0x6DB9,0x5F22,0x4EAB,0x3A14,0x2B9D,0x1906,0x088F, 0xE0F9,0xF170,0xC3EB,0xD262,0xA6DD,0xB754,0x85CF,0x9446, 0x6CB1,0x7D38,0x4FA3,0x5E2A,0x2A95,0x3B1C,0x0987,0x180E, 0xD17A,0xC0F3,0xF268,0xE3E1,0x975E,0x86D7,0xB44C,0xA5C5, 0x5D32,0x4CBB,0x7E20,0x6FA9,0x1B16,0x0A9F,0x3804,0x298D, 0xC1FB,0xD072,0xE2E9,0xF360,0x87DF,0x9656,0xA4CD,0xB544, 0x4DB3,0x5C3A,0x6EA1,0x7F28,0x0B97,0x1A1E,0x2885,0x390C, 0xB27C,0xA3F5,0x916E,0x80E7,0xF458,0xE5D1,0xD74A,0xC6C3, 0x3E34,0x2FBD,0x1D26,0x0CAF,0x7810,0x6999,0x5B02,0x4A8B, 0xA2FD,0xB374,0x81EF,0x9066,0xE4D9,0xF550,0xC7CB,0xD642, 0x2EB5,0x3F3C,0x0DA7,0x1C2E,0x6891,0x7918,0x4B83,0x5A0A, 0x937E,0x82F7,0xB06C,0xA1E5,0xD55A,0xC4D3,0xF648,0xE7C1, 0x1F36,0x0EBF,0x3C24,0x2DAD,0x5912,0x489B,0x7A00,0x6B89, 0x83FF,0x9276,0xA0ED,0xB164,0xC5DB,0xD452,0xE6C9,0xF740, 0x0FB7,0x1E3E,0x2CA5,0x3D2C,0x4993,0x581A,0x6A81,0x7B08, 0x7470,0x65F9,0x5762,0x46EB,0x3254,0x23DD,0x1146,0x00CF, 0xF838,0xE9B1,0xDB2A,0xCAA3,0xBE1C,0xAF95,0x9D0E,0x8C87, 0x64F1,0x7578,0x47E3,0x566A,0x22D5,0x335C,0x01C7,0x104E, 0xE8B9,0xF930,0xCBAB,0xDA22,0xAE9D,0xBF14,0x8D8F,0x9C06, 0x5572,0x44FB,0x7660,0x67E9,0x1356,0x02DF,0x3044,0x21CD, 0xD93A,0xC8B3,0xFA28,0xEBA1,0x9F1E,0x8E97,0xBC0C,0xAD85, 0x45F3,0x547A,0x66E1,0x7768,0x03D7,0x125E,0x20C5,0x314C, 0xC9BB,0xD832,0xEAA9,0xFB20,0x8F9F,0x9E16,0xAC8D,0xBD04, 0x3674,0x27FD,0x1566,0x04EF,0x7050,0x61D9,0x5342,0x42CB, 0xBA3C,0xABB5,0x992E,0x88A7,0xFC18,0xED91,0xDF0A,0xCE83, 0x26F5,0x377C,0x05E7,0x146E,0x60D1,0x7158,0x43C3,0x524A, 0xAABD,0xBB34,0x89AF,0x9826,0xEC99,0xFD10,0xCF8B,0xDE02, 0x1776,0x06FF,0x3464,0x25ED,0x5152,0x40DB,0x7240,0x63C9, 0x9B3E,0x8AB7,0xB82C,0xA9A5,0xDD1A,0xCC93,0xFE08,0xEF81, 0x07F7,0x167E,0x24E5,0x356C,0x41D3,0x505A,0x62C1,0x7348, 0x8BBF,0x9A36,0xA8AD,0xB924,0xCD9B,0xDC12,0xEE89,0xFF00}; WORD CRCVal,i; CRCVal=0; for(i=0;i<length;i++) CRCVal=CRCTABLE[(CRCVal^=data[i]&0xFF)&0xFF]^(CRCVal>>8); reply[0]=CRCVal%256; reply[1]=CRCVal/256; }